"""Default style implementation, with rounded boxes and
up extrussions to expand items"""

import math
from numpy import *
from scopiavf.font.prerender import PrerenderedText


class Style( object ):
    "Rounded treemap style inherited from treemap style base class"
    
    def __init__(self, context):
        self.context = context

    def drawNode( self, context, node ):
        "Draws a flat box with rounded corners and the text on it"
        rx = node.xradius
        ry = node.yradius
        #alpha = 1.0 - node.expansion*0.6
        alpha = 1.0
        space = min( rx, ry ) * 0.05
        rx -= space
        ry -= space
        basecolor = node.styleProps['color'] + (alpha,)
        basetextcolor = node.styleProps['textcolor'] + (alpha,)
        try: geometry = node._nodeGeometry
        except: geometry = node._nodeGeometry = nodeGeometry( context, node.text, rx, ry )
        body, text, border1, border2, border3, border4 = geometry

        context.setColorA(*basecolor)
        context.drawTriangleFanArray( border1 )
        context.drawTriangleFanArray( border2 )
        context.drawTriangleFanArray( border3 )
        context.drawTriangleFanArray( border4 )
        context.drawQuadArray( body )
        context.setColorA(*basetextcolor)
        text.draw( context )
    
    def drawBranch( self, context, branch ):
        """Draws a simple box extruding the flat box of a node and with a
           gradient of color from the base to the top."""
        xr, yr = branch.xradius, branch.yradius
        border = branch.mindim * 0.025
        xr -= border
        yr -= border
        H = branch.height
        alpha = branch.visible
        center = array( branch.center, float32 )
        basecolor = array( branch.styleProps['color'] + (alpha,) , float32 )
        pcolor = basecolor*array(0.5,float32) + array( (0.5, 0.5, 0.5, alpha),float32)
        offset = array( (0,0,min(xr,yr)*0.005), float32 )
        p = ( (xr, yr, 0), (-xr, yr, 0), (-xr, -yr, 0), (xr, -yr, 0),
                    (xr, yr, -H), (-xr, yr, -H), (-xr, -yr, -H), (xr, -yr, -H))
        c = array( ( (1.0, 1.0, 1.0, alpha), (0.9, 0.9, 0.9, alpha), pcolor ), float32 )
        quads = array( ( p[0], p[1], p[2], p[3], 
                                         p[1], p[0], p[4], p[5],
                                         p[2], p[1], p[5], p[6], p[3], p[2], p[6], p[7],
                                         p[0], p[3], p[7], p[4] ), float32 )
        colors = array( ( c[0], c[0], c[0], c[0],
                                        c[1], c[1], c[2], c[2],
                                        c[1], c[1], c[2], c[2], c[1], c[1], c[2], c[2],
                                        c[1], c[1], c[2], c[2] ), float32 )
        lines = array( ( p[0], p[1], p[1], p[2], p[2], p[3], p[3], p[0],
                                         p[0], p[4], p[1], p[5], p[2], p[6], p[3], p[7] ), float32 )
        quads += center
        quads -= offset
        lines *= array( 1.001 , float32 )
        lines += center
        lines -= offset
        context.setColorA(0.9, 0.9, 0.9, alpha)
        context.drawQuadArray( quads, None, colors )
        context.setColorA(0.7, 0.7, 0.7, alpha)
        context.drawLineArray( lines )

steps = 20

def nodeGeometry( context, text, xradius, yradius ):
    """Returns a tuple with the geometry to draw a node box:
       |    ( 5 quads in point array (20, 3) -> center quad, up, down, left and right quads,
       |      prerendered text instance,
       |      triangle fan for up right corner,
       |      triangle fan for up left corner,
       |      triangle fan for down left corner,
       |      triangle fan for down right corner )"""
    border = min( xradius, yradius ) * 0.15
    csteps = steps / 4
    p1=solidArc( 0, math.pi*0.5, 5, array((xradius - border,yradius - border,0.0), 'f'), border )
    p2=solidArc(math.pi*0.5,math.pi, 5, array((-xradius + border,yradius - border,0.0), 'f'), border )
    p3=solidArc(math.pi, math.pi*1.5, 5, array((-xradius + border,-yradius + border,0.0), 'f'), border )
    p4=solidArc(math.pi*1.5, math.pi*2, 5,array((xradius - border,-yradius + border,0.0), 'f'), border )
    p = zeros( (16, 3) ,'f')
    borderY = array( (0.0, border, 0.0), 'f')
    borderX = array( (border, 0.0, 0.0), 'f')
    p[:2] = ( (xradius - border, yradius, 0.0 ), ( -xradius + border, yradius, 0.0 ) )
    p[2:4] = p[1::-1] - borderY
    p[4:6] = ( ( -xradius + border, -yradius, 0.0 ), ( xradius - border, -yradius, 0.0 ) )
    p[6:8] = p[5:3:-1] + borderY
    p[8:10] = ( ( xradius, -yradius + border, 0.0 ), ( xradius, yradius - border, 0.0 ) )
    p[10:12] = p[9:7:-1] - borderX
    p[12:14] = ( ( -xradius, yradius - border, 0.0 ), ( -xradius, -yradius + border, 0.0 ) )
    p[14:16] = p[13:11:-1] + borderX
    points = array( ( (-xradius + border, -yradius + border, 0.0 ), 
                         ( xradius - border, -yradius + border, 0.0 ),
                         ( xradius - border,  yradius - border, 0.0 ),
                         (-xradius + border,  yradius - border, 0.0 )), 'f' )
    p = concatenate(( p, points ))
    points += array(0.005*min(xradius, yradius), float32)
    textgeom = PrerenderedText(context, text, points)
    return ( p, textgeom, p1, p2, p3, p4 )

def solidArc(angle1, angle2, steps, center, radius):
    """Builds an arc from angle1 to angle2 as a triangle fan

            angle1          Starting angle
            angle2          End angle
            steps           Number of divisions of the arc
            center          Center of the arc
            radius          Distance from the center to the border"""
    radius = array(radius, 'f')
    step = (angle2 - angle1) / float(steps)
    step2 = step*0.5
    p = zeros( (steps + 2, 3), 'f')
    p[1:,0] = cos( arange( angle1, angle2+step2, step, 'f' ) ) * radius
    p[1:,1] = sin( arange( angle1, angle2+step2, step, 'f' ) ) * radius
    return p + center
